#include <stdio.h>
#include <stdlib.h>
#include <string.h>

/* 学生信息结构体 */
typedef struct Student {
    int num;          // 序号（自动生成，从1开始递增）
    char id[20];      // 学号（唯一，用于排序和查找）
    char name[50];    // 姓名
    char gender[10];  // 性别（男/女）
    int age;          // 年龄
    struct Student *next;  // 指向下一个节点
} Student;

//全局链表头
Student* head = NULL;

//项目中的添加函数
//创建新节点
Student* create_student(int num, const char *id, const char *name, const char *gender, int age) {
    Student *new_node = (Student*)malloc(sizeof(Student));
    if (new_node == NULL) {
        perror("分配内存失败");
        return NULL;
    }
    // 赋值成员变量
    new_node->num = num;
    strcpy(new_node->id, id);
    strcpy(new_node->name, name);
    strcpy(new_node->gender, gender);
    new_node->age = age;
    new_node->next = NULL;
    return new_node;
}
//添加学生信息（按学号升序）
int add_student(int num, const char *id, const char *name, const char *gender, int age) {

    // 1. 检查学号是否已存在
    Student *temp = head;
    while (temp != NULL) {
        if (strcmp(temp->id, id) == 0) {
            return -1;  // 学号已存在
        }
        temp = temp->next;
    }

    // 2. 创建新节点
    Student *new_node = create_student(num, id, name, gender, age);
    if (new_node == NULL) {
        return -1;
    }

    // 3. 按学号升序插入（strcmp比较字符串大小）
    // 情况1：链表为空，直接作为头节点
    if (head == NULL) {
        head = new_node;
        return 0;
    }

    // 情况2：插入到链表头部（新学号 < 头节点学号）
    if (strcmp(new_node->id, head->id) < 0) {
        new_node->next = head;
        head = new_node;
        return 0;
    }

    // 情况3：插入到链表中间或尾部
    Student *prev = head;
    temp = head->next;
    while (temp != NULL) {
        if (strcmp(new_node->id, temp->id) < 0) {  // 找到插入位置
            prev->next = new_node;
            new_node->next = temp;
            return 0;
        }
        prev = temp;
        temp = temp->next;
    }

    // 情况4：插入到尾部（新学号最大）
    prev->next = new_node;
    return 0;
}

//删除学生信息（按学号）
int delete_student(const char *id) {

    Student *temp = head;
    Student *prev = NULL;

    // 查找要删除的节点
    while (temp != NULL) {
        if (strcmp(temp->id, id) == 0) {  // 找到节点
            // 情况1：删除头节点
            if (prev == NULL) {
                head = temp->next;
            } else {  // 情况2：删除中间或尾部节点
                prev->next = temp->next;
            }
            free(temp);  // 释放内存
            return 0;
        }
        prev = temp;
        temp = temp->next;
    }

    // 未找到节点
    return -1;
}

//获取学生数量（用于测试验证）
int get_student_num() {
    int num = 0;
    Student* p = head;
    while(p != NULL) {
        num++;
        p = p->next;
    }
    return num;
}

//清空链表（测试后进行清理）
void clear_all() {
    Student* p = head;
    while(p != NULL) {
        Student* temp = p;
        p = p->next;
        free(temp);
    }
    head = NULL;
}

//打印测试结果
//通过--0  失败-- -1
void print_result(const char *test_name, int expected, int actual, int result) {
    printf("测试用例：%s\n", test_name);
    printf("预期结果：%d\n", expected);
    printf("实际结果：%d\n", actual);
    printf("是否符合预期：%s\n\n", result ? "是" : "否");
}

//打印所有学生信息
void print_all_students() {
    Student* p = head;
    int num = 1;
    while(p != NULL) {
        printf("%d %s %s %s %d\n", num, p->id, p->name, p->gender, p->age);
        p = p->next;
        num++;
    }
}

int main() {
    int test_num = 0;   //测试用例数量
    int pass_num = 0;   //通过的用例数量
    int result;         //单个测试结果

    printf("=========学生添加功能测试开始==========\n\n");

    //测试用例1：正常添加学生信息
    test_num++;
    clear_all();    //清空链表，确保链表为空
    result = add_student(1,"SZ001", "张三", "男", 18);

    int num1 = get_student_num();
    int test1 = (result == 0 && num1 == 1) ? 1 : 0;
    pass_num += test1;
    print_result("测试用例1：正常添加学生信息",0,result,test1);
    printf("当前学生信息链表：\n");
    print_all_students();

    //测试用例2：添加第二个不同学号的学生信息
     test_num++;
    result = add_student(2,"SZ002", "李四", "男", 20);
    int num2 = get_student_num();
    int test2 = (result == 0 && num2 == 2) ? 1 : 0;
    pass_num += test2;
    print_result("测试用例2：正常添加学生信息",0,result,test2);
    printf("当前学生信息链表：\n");
    print_all_students();

    //测试用例3：添加一个重复学号的学生信息（预期不通过）检查学号唯一性
    test_num++;
    result = add_student(3,"SZ001", "王五", "女", 22);   
    int num3 = get_student_num();
    int test3 = (result == -1 && num3 == 2) ? 1 : 0;
    pass_num += test3;
    print_result("测试用例3：添加一个重复学号的学生信息（预期系统会拒绝，无法添加）",-1,result,test3);
    printf("当前学生信息链表：\n");
    print_all_students();

    //测试用例4：添加第三个不同学号的学生信息，验证学号升序
    test_num++;
    result = add_student(3,"SZ000", "李例", "男", 21);
    int num4 = get_student_num();
    int test4 = (result == 0 && num4 == 3) ? 1 : 0;
    pass_num += test4;
    print_result("测试用例4：正常添加学生信息，验证学号升序",0,result,test4);
    printf("当前学生信息链表：\n");
    print_all_students();

    //测试总结
    printf("=========学生添加功能测试结束==========\n");
    printf("测试用例总数量：%d\n", test_num);
    printf("通过的用例数量：%d\n", pass_num);
    printf("失败的用例数量：%d\n", test_num - pass_num);
    printf("当前学生信息链表：\n");
    print_all_students();
    //清理
    clear_all();
    return 0;
    
}